#ifndef UNIVERSAL_MASTER_HPP
#define UNIVERSAL_MASTER_HPP

#include <string>
#include <vector>

typedef void(__stdcall* UniMasterLogCallbackY)(std::string name, std::string id,
	std::string type, std::vector<uint8_t> log);
typedef void(__stdcall* UniMasterLogStateCallbackZ)(std::string name, std::string id,
	std::string type, std::vector<uint8_t> log, std::vector<uint8_t> state);

struct UniversalMaster {
	struct Flags {
		int simuMode = 0;
	}_flags;

	// set directly
	struct Meta {
		std::string platform;
		std::string appearance;
		std::string model;
		std::string identifier;
		std::string referenceName;
	}_meta;

	// set directly by master
	struct Callbacks {
		bool flagEnable = false;
		// send result to master
		UniMasterLogCallbackY sentCB = NULL;
		UniMasterLogStateCallbackZ replyCB = NULL;
		UniMasterLogStateCallbackZ timeoutCB = NULL;
		std::string allCBBuffer;
	}_callbacks;

	struct Misc {
		std::string nameInLog;
		void* slave = nullptr;
	}_misc;

	const int SLAVE_TIME_OUT_MS = 100;

	//static UniversalMaster* makeNewAndConnect(std::wstring platform, std::wstring appearance, std::wstring model, std::wstring identifier);

	UniversalMaster();
	~UniversalMaster();

	int init(int simuMode = 0);
	void setCommLog(bool newFlag) { _callbacks.flagEnable = newFlag; };

	int issueCommand(std::string command, std::string paras);
	// timeout = 0
	int comfirmReply(std::string reply, int timeout);
	//int comfirmAnyReply(int timeout);
	int flush();

	// called by slave
	void serialSentCB(bool success, const void* log, int logLen, const void* data, int dataLen);
	// called by slave
	void serialReceiveCB(bool success, const void* log, int logLen, const void* data, int dataLen);
	void addToAllBuffer(const std::string& in);
	void clearAllBuffer() { _callbacks.allCBBuffer.clear(); }
	std::string getAllBuffer() { return _callbacks.allCBBuffer; };

	static void serialSentCBWrap(int index, bool success, const void* log, int logLen, const void* data, int dataLen);
	static void serialReceiveCBWrap(int index, bool success, const void* log, int logLen, const void* data, int dataLen);

private:
	int callbackIndex = -1;

	static int addMeToArray(UniversalMaster* myPtr);
	static void removeMeFromArray(int index);
	static std::vector<UniversalMaster*> allMasters;
};


#endif